/* Copyright (C) 2010 Luca Piccinelli
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* 
 * File:   pipeline_io.h
 * Author: lpiccinelli
 *
 * Created on 29 luglio 2010, 22.10
 */

#ifndef _PIPELINE_IO_H
#define	_PIPELINE_IO_H

#include <cassert>
#include <string>

#include <boost/any.hpp>

#include "prj_definitions.h"
#include "common/utility_data_structures.h"
#include "exceptions/pipeline_exceptions.h"

namespace NAMESPACE{

// ****** IOElement interface **************************************************
class IOElement{
public:
    virtual ~IOElement(){}
    virtual boost::any& getElement() const = 0;
    virtual void setElement(boost::any* const element) = 0;
    virtual const IOKey& getIOKey() const = 0;
    virtual IOElement& setIOKey(const IOKey& k) = 0;
    virtual IOElement& setIOKey(const char* _ns, const char* _key_name) = 0;
    virtual IOElement& setIOKey(const std::string& _ns, std::string& _key_name) = 0;
    virtual IOElement& setIOKey(const std::string& _ns, std::string& _key_name, const std::string& type) = 0;

    virtual bool operator==(const IOElement& _element) const = 0;
    virtual bool operator!=(const IOElement& _element) const = 0;
};
// -----------------------------------------------------------------------------

// ****** GenericIOElement definition *****************************************

class GenericIOElement : public IOElement{
public:
    typedef boost::any element_t;

protected:
    element_t* element;
    IOKey* io_key;

public:
    virtual ~GenericIOElement();
    GenericIOElement();
    GenericIOElement(const GenericIOElement& gie);
    GenericIOElement& operator=(const GenericIOElement& gie);

    GenericIOElement(const IOKey& k);

    virtual boost::any& getElement() const throw(bad_element);
    virtual void setElement(boost::any* const element);
    virtual const IOKey& getIOKey() const;
    virtual IOElement& setIOKey(const IOKey& k);
    virtual IOElement& setIOKey(const char* _ns, const char* _key_name);
    virtual IOElement& setIOKey(const std::string& _ns, std::string& _key_name);
    virtual IOElement& setIOKey(const std::string& _ns, std::string& _key_name, const std::string& type);

    virtual bool operator==(const IOElement& _element) const;
    virtual bool operator!=(const IOElement& _element) const;
};

// -----------------------------------------------------------------------------

// ****** HandledIOElement definition ******************************************

class HandledIOElement : public GenericIOElement{

public:
    virtual ~HandledIOElement();
    HandledIOElement();
    HandledIOElement(const HandledIOElement& _element);
    template<typename T>
    HandledIOElement(const T& _element);
    
    HandledIOElement& operator=(const HandledIOElement& gie);

    virtual void setElement(boost::any* const element);

    HandledIOElement(const IOKey& k);
    template<typename T>
    HandledIOElement(const T& _element, const IOKey& k) : GenericIOElement(k){
        element = new element_t(_element);
        io_key->setType(TypeParseTraits<T>::name());
    }

    virtual bool operator==(const IOElement& _element) const;
    virtual bool operator!=(const IOElement& _element) const;
};

// -----------------------------------------------------------------------------

// ****** NumericIOElement definition ******************************************

class NumericIOElement : public HandledIOElement{

public:
    virtual ~NumericIOElement();
    NumericIOElement();
    NumericIOElement(const NumericIOElement& gie);
    NumericIOElement& operator=(const NumericIOElement& gie);

    virtual void setElement(boost::any* const element) throw(bad_element);

    NumericIOElement(int n);
    NumericIOElement(double n);
    NumericIOElement(float n);
    
    NumericIOElement(int n, const IOKey& k);
    NumericIOElement(double n,const IOKey& k);
    NumericIOElement(float n, const IOKey& k);

    virtual bool operator==(const IOElement& _element) const;
    virtual bool operator!=(const IOElement& _element) const;
};

// -----------------------------------------------------------------------------

}

#endif	/* _PIPELINE_IO_H */

